﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Inaction;
using Inaction.ServiceContract;
using System.IO;
using System.Reflection;

namespace Inaction
{
    public static class ServiceContainer
    {
        static Lazy<Dictionary<string, ServiceItem>> cache = new Lazy<Dictionary<string, ServiceItem>>(() =>
        {
            var s = new System.Xml.Serialization.XmlSerializer(typeof(List<ServiceItem>));
            var fileName = Util.AppHelper.ConfigDirectory + "Services.xml";
            try
            {
                using (var stream = new FileStream(fileName, FileMode.Open))
                {
                    var buf = new byte[stream.Length];
                    stream.Read(buf, 0, buf.Length);
                    var ms = new MemoryStream(buf);
                    var list = (List<ServiceItem>)s.Deserialize(ms);
                    return list.ToDictionary(p => p.Service);
                }
            }
            catch
            {
                List<ServiceItem> list = new List<ServiceItem>();
                string[,] str = new string[,]
                {
                    {
                        "Inaction.ServiceContract.ICache",
                        "Inaction.Extensions;Inaction.Extensions.Cache.CacheManager"
                    },
                    {
                        "Inaction.ServiceContract.IEntityLoger",
                        "Inaction.Extensions;Inaction.Extensions.Log.EntityLoger" 
                    },
                    {
                        "Inaction.ServiceContract.IGetChangeLogType",
                        "Inaction.Extensions;Inaction.Extensions.Log.EntityLoger"  
                    } ,
                    {
                        "Inaction.ServiceContract.IEntityConfig",
                        "Inaction.Extensions;Inaction.Extensions.EntityConfig.EntityConfigHelper"
                    },
                    {
                        "Inaction.ServiceContract.IBusinessRuleAction",
                        "Inaction.Extensions;Inaction.Extensions.BusinessRule.BusinessRuleAction"
                    },
                    {
                        "Inaction.ServiceContract.IMessager",
                        "Inaction.Extensions;Inaction.Extensions.Message.Messager" 
                    },
                    {
                        "Inaction.DbProvider",
                        "Inaction.Database;Inaction.Database.DbProvider"
                    },
                    {
                        "Inaction.ServiceContract.ISecurityProvider",
                        "Inaction.Extensions;Inaction.Extensions.Security.SecurityProvider" 
                    },
                    {
                        "Inaction.ServiceContract.IZip",
                        "Inaction.Extensions;Inaction.Extensions.Zip.ZipHelper" 
                    },
                    {
                        "Inaction.ServiceContract.ISerializerHelper",
                        "Inaction.Extensions;Inaction.Extensions.Serialization.SerializerHelper" 
                    }
                };
                for (int i = 0; i < str.Length / str.Rank; i++)
                {
                    var item = new ServiceItem { IsSingle = true, Service = str[i, 0].Trim(), Type = str[i, 1].Trim() };
                    list.Add(item);
                }
                using (var writer = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
                {
                    s.Serialize(writer, list);
                    writer.Flush();
                }
                return list.ToDictionary(p => p.Service); ;
            }
        }, true);

        public static T GetService<T>() where T : class
        {
            if (cache.Value.ContainsKey(typeof(T).FullName))
            {
                return cache.Value[typeof(T).FullName].GetInstance<T>();
            }
            return null;
        }
    }

    public class ServiceItem
    {
        public string Service { get; set; }

        public string Type { get; set; }

        public bool IsSingle { get; set; }

        object instance = null;

        public T GetInstance<T>()
        {
            if (instance == null && !string.IsNullOrEmpty(Type))
            {
                var temp = Type.IndexOf(';');
                var ins = Inaction.Util.TypeHelper.CreateInstance(
                    Type.Substring(0, temp).Trim(),
                    Type.Substring(temp + 1).Trim());
                if (IsSingle)
                {
                    instance = ins;
                }
                else return (T)ins;
            }
            return (T)instance;
        }
    }
}